package testcase;

import database.DatabaseHelper;
import entity.*;

import java.sql.SQLException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;

public class Generator {
    private DatabaseHelper db;
    private Random r;

    public void run() {
        try {
            r = new Random();
            db = new DatabaseHelper();
            db.connection.setAutoCommit(false);
            student(100);
            course(3);
            teacher(6);
            section();
            take();
            score();
            db.connection.commit();
        } catch (Exception e) {
            System.out.println("发生错误！");
            e.printStackTrace();
            try {
                db.connection.rollback();
                System.out.println("回滚成功。");
            } catch (SQLException ex) {
                System.out.println("回滚失败！");
                ex.printStackTrace();
            }
        } finally {
            db.close();
        }
    }

    public static void main(String[] args) {
        Generator g = new Generator();
        g.run();
    }

    private static char randomCnChar() {
        final int start = '\u4e00';   // Unicode中第一个汉字的编码值为U+4E00
        final int end = '\u9fa5';     // Unicode中最后一个汉字的编码值为U+9FA5
        Random r = new Random();
        int index = r.nextInt((end - start + 1));
        return (char)(start + index);
    }

    private static String randomCnStr(int len) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < len; ++i) {
            sb.append(randomCnChar());
        }
        return sb.toString();
    }

    private static String randomCnStr(int minLen, int maxLen) {
        Random r = new Random();
        StringBuilder sb = new StringBuilder();
        int len = minLen + r.nextInt(maxLen - minLen + 1);
        return randomCnStr(len);
    }

    public void student(int number) throws SQLException {
        int i = 0;
        try {
            while (i < number) {
                String id;
                do {
                    id = String.format("%08d", 20000000 + r.nextInt(240000));
                } while (Student.find(db, id) != null);
                String name = randomCnStr(2, 4);
                String sex = r.nextBoolean() ? "男" : "女";
                Student.create(db, id, name, sex);
                ++i;
            }
        } catch (SQLException e) {
            System.out.println("在生成第"+(i + 1)+"个学生时失败！");
            throw e;
        }
        System.out.println("成功生成"+i+"个学生。");
    }

    public void course(int number) throws SQLException {
        int i = 0;
        try {
            while (i < number) {
                String id = String.format("%05d", r.nextInt(100000));
                if (Course.find(db, id) != null)
                    continue;
                String name = randomCnStr(4, 10);
                Course.create(db, id, name);
                ++i;
            }
        } catch (SQLException e) {
            System.out.println("在生成第"+(i + 1)+"个课程时失败！");
            throw e;
        }
        System.out.println("成功生成"+i+"个课程。");
    }

    public void teacher(int number) throws SQLException {
        int i = 0;
        try {
            while (i < number) {
                String id = String.format("t%08d", 20000000 + r.nextInt(240000));
                if (Teacher.find(db, id) != null)
                    continue;
                String name = randomCnStr(2, 4);
                Teacher.create(db, id, name);
                ++i;
            }
        } catch (SQLException e) {
            System.out.printf("在生成第%d个教师时失败！\n", i + 1);
            throw e;
        }
        System.out.printf("成功生成%d个教师。\n", number);
    }

    public void section() throws SQLException {
        ArrayList<Teacher> teachers = Teacher.findAll(db);
        ArrayList<Course> courses = Course.findAll(db);
        int i = 0;
        int j = 0;
        try {
            for (i = 0; i < courses.size(); ++i){
                Collections.shuffle(teachers);
                int secNum = 2 + r.nextInt(teachers.size() - 1);
                for (j = 0; j < secNum; ++j){
                    String id = String.format("%s-%d", courses.get(i).getId(), j + 1);
                    int maxSize = 20 + r.nextInt(100);
                    String[] semesters = {"2021秋", "2022春", "2022秋", "2023春", "2023秋", "2024春"};
                    String semester = semesters[r.nextInt(semesters.length)];
                    Section.create(db, id, maxSize, semester, courses.get(i), teachers.get(j));
                }
            }
        } catch (SQLException e) {
            System.out.printf("在为第%d个课程生成第%d个教学班时失败！\n", i, j);
            throw e;
        }
        System.out.println("成功为每个课程生成至少2个教学班。");
    }

    public void take() throws SQLException {
        ArrayList<Student> students = Student.findAll(db);
        ArrayList<Course> courses = Course.findAll(db);
        HashMap<String, ArrayList<Section>> sections = new HashMap<>();
        for (Iterator<Course> iterator = courses.iterator(); iterator.hasNext();) {
            Course cou = iterator.next();
            ArrayList<Section> secs = cou.getSections(db);
            if (secs.isEmpty()) {
                iterator.remove();
            } else {
                sections.put(cou.getId(), secs);
            }
        }
        for (Student stu : students) {
            Collections.shuffle(courses);
            int takeNum = Math.max(3, r.nextInt(courses.size()));
            Iterator<Course> iterator = courses.iterator();
            for (int i = 0; i < takeNum; ++i) {
                Course cou = iterator.next();
                ArrayList<Section> secs = sections.get(cou.getId());
                Section sec = secs.get(r.nextInt(secs.size()));
                sec.addStudent(db, stu);
                if(sec.countStudents(db) == sec.getMaxSize()) {
                    secs.remove(sec);
                    if (secs.isEmpty()) {
                        iterator.remove();
                    }
                }
            }
        }
        System.out.println("成功为每名学生分配至少3门课程。");
    }

    public void score() throws SQLException {
        for (Teacher tea: Teacher.findAll(db)) {
            for (Section sec: tea.getSections(db)) {
                for (Student stu: sec.getStudents(db)) {
                    Score.create(db, sec, stu);
                    Score sco = Score.find(db, sec, stu);
                    sco.setUsual(db, r.nextInt(10));
                    sco.setMidterm(db, r.nextInt(20));
                    sco.setExperiment(db, r.nextInt(20));
                    sco.setTerminal(db, r.nextInt(50));
                    sco.setTotal(db, sco.getUsual() + sco.getMidterm() + sco.getExperiment() + sco.getTerminal());
                    sco.setTimeStamp(db, LocalDateTime.ofInstant(Instant.now().plusMillis(r.nextInt()), ZoneId.systemDefault()));
                }
            }
        }
        System.out.println("成功为每名学生生成成绩。");
    }

}
